package com.easipass.unifiedconfig.unic;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.easipass.unifiedconfig.Parameter;
import com.easipass.unifiedconfig.UCI;
import com.easipass.unifiedconfig.Parameter.AccessLevel;

/**
 * 
 * @version $Id$
 * @author itea
 * @date 2010-3-1
 */
public class JsonPersistence implements Persistence {

	private File path;
	
	public JsonPersistence(File path) {
		super();
		this.path = path;
	}

	public Collection<Parameter> loadParameters(UCI range) throws IOException {
		InputStreamReader in = null;
		Set<Parameter> pset = new LinkedHashSet<Parameter>();
		
		char[] b = new char[1024];
		for(File f : path.listFiles()) {
			if(!f.isFile()) continue;
			in = new InputStreamReader(new FileInputStream(f), "UTF-8");
			try {
				ByteArrayOutputStream bo = new ByteArrayOutputStream((int)f.length());
				OutputStreamWriter w = new OutputStreamWriter(bo, "UTF-8");
				while(true) {
					int len = in.read(b);
					if(len <0) break;
					w.write(b, 0, len);
				}
				w.flush();
				JSONObject jo = new JSONObject(bo.toString(w.getEncoding()));
				Parameter p = new Parameter(jo.getString("uci"));
				p.setAccessLevel(AccessLevel.valueOf(jo.getString("acc")));
				String[] vals = new String[jo.getJSONArray("values").length()];
				for(int i=0; i<vals.length; i++)
					vals[i] = jo.getJSONArray("values").getString(i);
				p.setValues(vals);
				
				pset.add(p);
			} catch (JSONException e) {
				e.printStackTrace();
			} finally {
				in.close();
			}
		}
		return pset;
	}

	public void remove(Parameter p) throws IOException {
		File f = new File(path, uci2filename(p.getUci()));
		if(f.exists() && f.isFile())
			f.delete();
	}

	public void save(Parameter p) throws IOException {
		File f = new File(path, uci2filename(p.getUci()));
		OutputStreamWriter out = null;
		try {
			out = new OutputStreamWriter(new FileOutputStream(f), "UTF-8");
			JSONObject jo = new JSONObject();
			try {
				jo.put("uci", p.getUci().toString());
				jo.put("acc", p.getAccessLevel());
				jo.put("values", new JSONArray(p.getValues()));
				jo.write(out);
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		} finally {
			if(out != null) out.close();
		}
		
	}

	static final String uci2filename(UCI u) {
		StringBuilder sb = new StringBuilder(u.getDomain());
		sb.append("__").append(u.getAccount())
			.append("[").append(u.getModule()).append("]")
			.append("__").append(u.getParameterName());
		return sb.toString().replaceAll("/", "__");
	}
	
	public static final String md5(String s) {
		try {
			char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
					'9', 'a', 'b', 'c', 'd', 'e', 'f' };
			char str[];
			byte strTemp[] = s.getBytes();
			MessageDigest mdTemp = MessageDigest.getInstance("MD5");
			mdTemp.update(strTemp);
			byte md[] = mdTemp.digest();
			int j = md.length;
			str = new char[j * 2];
			int k = 0;
			for (int i = 0; i < j; i++) {
				byte byte0 = md[i];
				str[k++] = hexDigits[byte0 >>> 4 & 0xf];
				str[k++] = hexDigits[byte0 & 0xf];
			}
			return new String(str);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return null;
		}
	}
}
